/**
 * @author tshepo
 *
 */
package fr.toto.triseries;

import java.awt.AWTException;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.plaf.synth.SynthLookAndFeel;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.LocalizedMessage;

import com.kokotchy.betaSeriesAPI.UtilsXml;
import com.kokotchy.betaSeriesAPI.api.xmlImpl.BetaSerieApi;
import com.kokotchy.betaSeriesAPI.model.Episode;
import com.kokotchy.betaSeriesAPI.model.SubtitleLanguage;
import com.sun.net.httpserver.HttpServer;

import fr.toto.constantes.Constantes;
import fr.toto.exceptions.ProcessException;
import fr.toto.files.AccesFile;
import fr.toto.files.WatchDir;
import fr.toto.menuitem.MyPopupMenu;
import fr.toto.settings.Settings;
import fr.toto.subtitles.Soutitre;
import fr.toto.subtitles.SoutitreSet;
import fr.toto.webui.MyHandler;

public class Main implements Constantes {

	public static DetailFile af;
	public static String token;
	private static MySplashScreen splash;
	private static TrayIcon trayIcon;
	private final static ScheduledExecutorService scheduler = Executors
			.newScheduledThreadPool(1);

	private static final Logger logger = LogManager.getLogger(Main.class);

	/**
	 * Démarrage de l'Application
	 */
	public static void main(String[] args) {

		splash = MySplashScreen.getSplashScreen();

		loadLookAndFeel();

		BetaSerieApi.setApiKey(APIKEY);

		UtilsXml.setUserAgent(PGMNAME + "." + VERSION + " - "
				+ System.getProperty("os.name").toString());

		if (!SystemTray.isSupported()) {
			JOptionPane.showMessageDialog(null,
					MESSAGES.getString("ErrorSupportSysTrayMsg"));
		} else {

			if (Settings.LoadSettings()) {

				UtilsXml.setUserAgent(PGMNAME + "." + VERSION + " - "
						+ System.getProperty("os.name").toString() + " - "
						+ settings.getLogin());

				af = new DetailFile();

				// Création du MenuPopup
				createIconTray();

				// Chargement de la liste des séries
				splash.displayMessage("Téléchargement liste des séries");
				BetaSeriesQuery.iniSeriesSet();

				// Chargement de la liste des épisodes a regarder
				splash.displayMessage("Téléchargement liste des épisodes a voir");
				BetaSeriesQuery.InitEpisodeSet();

				// Ajout du PopupMenu
				addPopupMenu();

				// Recherche des Soustitres disponibles
				searchForSubtitles();

				// Recherche de la présence des vidéos non téléchargés
				searchForDownloadedVideo();

				// Démarrage de l'interface Web
				if (settings.useWebUI()) {
					startWebUI();
				}

				// Démarrage de la survéillance des dossiers
				startWatchDir();

				splash.close();

			}
		}

	}

	private static void loadLookAndFeel() {
		logger.trace(new LocalizedMessage(DEBUGMSG,
				"fr.toto.triseries.Main.loadLookAndFeel", null));
		try {
			if (Files.exists(LOOKXMLPATH)) {
				SynthLookAndFeel synth = new SynthLookAndFeel();
				synth.load(LOOKXMLPATH.toUri().toURL());
				UIManager.setLookAndFeel(synth);
			}// else

			// UIManager.setLookAndFeel(UIManager
			// .getSystemLookAndFeelClassName());
		} catch (Exception e) {
			logger.warn(new LocalizedMessage(ERRORMSG,
					"fr.toto.triseries.Main.loadLookAndFeel", null), e);
		}
	}

	private static void addPopupMenu() {		
		logger.trace(new LocalizedMessage(DEBUGMSG,
				"fr.toto.triseries.Main.addPopupMenu", null));

		splash.displayMessage("Ajout du Menu");
		trayIcon.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				if (e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON3) {
					MyPopupMenu ppm = new MyPopupMenu();
					ppm.generateMenu();
					ppm.setLocation(e.getX(), e.getY());
					ppm.setInvoker(ppm);
					ppm.setVisible(true);
				}
			}
		});

		trayIcon.setImage(iconWait);
	}

	private static void createIconTray() {
		logger.trace(new LocalizedMessage(DEBUGMSG,
				"fr.toto.triseries.Main.createIconTray", null));
		trayIcon = new TrayIcon(iconBusy, PGMNAME);
		trayIcon.setImageAutoSize(true);
		try {
			SystemTray.getSystemTray().add(trayIcon);
		} catch (AWTException e1) {

			logger.error(new LocalizedMessage(ERRORMSG,
					"fr.toto.triseries.Main.createIconTray", null), e1);
			JOptionPane.showMessageDialog(
					null,
					MESSAGES.getString("ErrorSupportSysTrayMsg")
							+ e1.toString());
		}
		trayIcon.setToolTip(PGMNAME + "." + VERSION);
	}

	private static void startWatchDir() {
		logger.trace(new LocalizedMessage(DEBUGMSG,
				"fr.toto.triseries.Main.startWatchDir", null));

		splash.displayMessage("Ajout des Dossiers a Surveiller");
		try {
			WatchDir w = new WatchDir(settings.getScanDir(),
					settings.isRecursiveScan(), af);
			new Thread(w).start();
		} catch (IOException e) {
			logger.error(new LocalizedMessage(ERRORMSG,
					"fr.toto.triseries.Main.startWatchDir", null), e);
			new ProcessException(e);
		}
	}

	private static void searchForSubtitles() {
		logger.trace(new LocalizedMessage(DEBUGMSG,
				"fr.toto.triseries.Main.searchForSubtitles", null));
		// Recherche des Soustitres disponibles
		splash.displayMessage("Recherche de soustitres");
		SoutitreSet.Load();
		for (Object s : SoutitreSet.ListATraiter()) {
			if (s instanceof Soutitre) {
				af.executer((Soutitre) s);
			}
		}
		af.executer(new Soutitre("", 0, 0, SubtitleLanguage.UNKNOWN, ""));

		// programmation des nouvelles recherche tous les 6 heures
		UpdateSeries us = new UpdateSeries(af);
		scheduler.scheduleAtFixedRate(us, 6, 6, TimeUnit.HOURS);

	}

	private static void searchForDownloadedVideo() {
		logger.trace(new LocalizedMessage(DEBUGMSG,
				"fr.toto.triseries.Main.searchForDownloadedVideo", null));
		splash.displayMessage("Recherche des Vidéos déjà stokés");
		// Recherche de la présence des vidéos non téléchargés
		for (Object ep : EpisodesSet.ListATraiter()) {
			if (ep instanceof Episode)
				if (!((Episode) ep).isDownloaded()) {
					Path file = AccesFile.Find((Episode) ep);
					if (file != null) {
						BetaSeriesQuery.setDownloaded((Episode) ep);
						((Episode) ep).setDownloaded(true);
					}
				}
		}
	}

	private static void startWebUI() {
		logger.trace(new LocalizedMessage(DEBUGMSG,
				"fr.toto.triseries.Main.startWebUI", null));
		splash.displayMessage("Démarrage de l'interface Web");
		InetSocketAddress addr = new InetSocketAddress(settings.getPortWebUI());
		HttpServer server;
		try {
			server = HttpServer.create(addr, 0);
			server.createContext("/", new MyHandler());
			server.setExecutor(Executors.newCachedThreadPool());
			server.start();
		} catch (IOException e1) {
			logger.warn(new LocalizedMessage(ERRORMSG,
					"fr.toto.triseries.Main.startWebUI", null), e1);
			if (e1 instanceof BindException) {
				String m = String.format(MESSAGES.getString("BindException"),
						e1.getMessage());
				JOptionPane.showMessageDialog(null, m.toString());
			}
		}
	}

	public static Properties MenuProperties() {
		Properties p = new Properties();
		try {
			if (Files.exists(MENUTXTPATH)) {
				p.load(new InputStreamReader(new FileInputStream(MENUTXTPATH
						.toString()), CharsetName));
			} else {
				p.load(new InputStreamReader(Main.class
						.getResourceAsStream("/fr/toto/menuitem/menu.txt"),
						CharsetName));
			}
		} catch (Exception e) {
			new ProcessException(e);
			logger.error(new LocalizedMessage(ERRORMSG,
					"fr.toto.triseries.Main.MenuProperties", null), e);
		}
		return p;
	}

	public static Properties initSeriesFile() {
		Properties seriesFile = new Properties();
		try {
			seriesFile.load(new InputStreamReader(new FileInputStream(
					LISTSHOWPATH.toString()), CharsetName));
		} catch (Exception e) {
			return new Properties();
		}
		return seriesFile;
	}

}
